package top.korori.sv.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.korori.sv.entity.dto.SvProvinceUserNumDto;
import top.korori.sv.entity.dto.SvSexRatioDto;
import top.korori.sv.entity.dto.WorkDayBrowseDto;
import top.korori.sv.entity.dto.VideoNumberCountDto;
import top.korori.sv.entity.vo.*;
import top.korori.sv.enums.SvUserSex;
import top.korori.sv.mapper.SvCountMapper;
import top.korori.sv.mapper.SvUserAreaMapper;
import top.korori.sv.service.SvCountService;
import top.korori.sv.service.SvUserService;
import top.korori.sv.entity.SvUser;
import top.korori.sv.entity.SvUserArea;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
public class SvCountServiceImpl implements SvCountService {

    @Autowired
    private SvCountMapper svCountMapper;

    @Autowired
    private SvUserAreaMapper svUserAreaMapper;

    @Autowired
    private SvUserService svUserService;

    @Override
    public SvNumberVo numberCount() {
        VideoNumberCountDto videoNumberCountDto = svCountMapper.numberCount();
        SvNumberVo svNumberVo = BeanUtil.copyProperties(videoNumberCountDto, SvNumberVo.class);
        svNumberVo.setWorkDayCompare(calculateGrowthRate(videoNumberCountDto.getTodayWorkTotal(), videoNumberCountDto.getYesterdayWorkTotal()));
        svNumberVo.setUserDayCompare(calculateGrowthRate(videoNumberCountDto.getTodayUserTotal(), videoNumberCountDto.getYesterdayUserTotal()));
        svNumberVo.setLikeDayCompare(calculateGrowthRate(videoNumberCountDto.getTodayLikeTotal(), videoNumberCountDto.getYesterdayLikeTotal()));
        svNumberVo.setBrowseDayCompare(calculateGrowthRate(videoNumberCountDto.getTodayBrowseTotal(), videoNumberCountDto.getYesterdayBrowseTotal()));
        return svNumberVo;
    }

    @Override
    public SvDayBrowseVo dayBrowse() {

        List<WorkDayBrowseDto> workDayBrowseDtoList = svCountMapper.dayBrowse();

        //生成近15天日期给vo设置,因为如果sql查询某一天浏览为零蛋,那一天日期就没有了,只能靠代码补
        LocalDate today = LocalDate.now();
        List<LocalDate> dates = IntStream
                .rangeClosed(0, 14)
                .mapToObj(today::minusDays)
                .sorted(Comparator.naturalOrder())
                .collect(Collectors.toList());
        SvDayBrowseVo svDayBrowseVo = new SvDayBrowseVo();
        svDayBrowseVo.setDate(dates);

        List<Long> browseList = new ArrayList<>();


        svDayBrowseVo.getDate().forEach(dateVo -> {
            Long browse = workDayBrowseDtoList.stream()
                    .filter(dateDto -> ObjUtil.equal(dateDto.getDate(), dateVo))
                    .map(WorkDayBrowseDto::getBrowse)
                    .findFirst()
                    .orElse(0L);
            browseList.add(browse);
        });

        svDayBrowseVo.setBrowse(browseList);
        return svDayBrowseVo;
    }

    @Override
    public List<SvSexRatioVo> sexRatio() {

        List<SvSexRatioDto> svSexRatioDtos = svCountMapper.sexRatio();

        List<SvSexRatioVo> svSexRatioVos = new ArrayList<>();

        Arrays.stream(SvUserSex.values()).forEach(sexEnum -> {
            Long total = svSexRatioDtos.stream()
                    .filter(dto -> ObjUtil.equal(sexEnum.getSex(), dto.getSex()))
                    .map(SvSexRatioDto::getTotal)
                    .findFirst()
                    .orElse(0L);


            SvSexRatioVo svSexRatioVo = new SvSexRatioVo();
            svSexRatioVo.setSex(sexEnum.getSex() == null ? -1 : sexEnum.getSex());
            svSexRatioVo.setTotal(total);
            svSexRatioVos.add(svSexRatioVo);

        });


        return svSexRatioVos;
    }

    @Override
    public List<SvProvinceUserNumVo> provinceUserNum() {

        List<SvProvinceUserNumDto> provinceUserNumDtos = svCountMapper.provinceUserNum();
        LambdaQueryWrapper<SvUserArea> svUserAreaQueryWrapper = new LambdaQueryWrapper<>();
        svUserAreaQueryWrapper.eq(SvUserArea::getParentId,0);
        List<SvUserArea> svUserAreas = svUserAreaMapper.selectList(svUserAreaQueryWrapper);

        List<SvProvinceUserNumVo> svProvinceUserNumVos = new ArrayList<>();

        svUserAreas.forEach(svUserArea -> {
            SvProvinceUserNumVo svProvinceUserNumVo = new SvProvinceUserNumVo();
            svProvinceUserNumVo.setProvince(svUserArea.getName());
            Long total = provinceUserNumDtos.stream()
                    .filter(provinceUserNum -> ObjUtil.equal(svUserArea.getName(), provinceUserNum.getProvince()))
                    .map(SvProvinceUserNumDto::getTotal)
                    .findFirst()
                    .orElse(0L);
            svProvinceUserNumVo.setTotal(total);
            svProvinceUserNumVos.add(svProvinceUserNumVo);
        });

        SvProvinceUserNumVo svProvinceUserNumVo = new SvProvinceUserNumVo();

        Long total = provinceUserNumDtos.stream()
                .filter(provinceUserNum -> ObjUtil.isEmpty(provinceUserNum.getProvince()))
                .map(SvProvinceUserNumDto::getTotal)
                .findFirst()
                .orElse(0L);
        svProvinceUserNumVo.setProvince("未知");
        svProvinceUserNumVo.setTotal(total);
        svProvinceUserNumVos.add(svProvinceUserNumVo);

        return svProvinceUserNumVos;
    }

    @Override
    public List<SysSvUserVo> userRanking() {
        LambdaQueryWrapper<SvUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(SvUser::getBrowseNum);
        queryWrapper.last("LIMIT 10");
        List<SvUser> svUsers = svUserService.list(queryWrapper);
        return BeanUtil.copyToList(svUsers, SysSvUserVo.class);
    }

    private static String calculateGrowthRate(Long todayValue, Long yesterdayValue) {

        if ( yesterdayValue == 0L && todayValue == 0L) {
            return "0";
        }

        if (yesterdayValue == 0L) {
            return "100"; // 避免除以零
        }
        double growthRate = ((todayValue - yesterdayValue) / (double) yesterdayValue) * 100;

        // 限制两位小数
        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        return decimalFormat.format(growthRate);
    }

    /**
     * 计算差值
     *
     * @param todayValue     今天的值
     * @param yesterdayValue 昨天的值
     * @return 差值
     */
    private static Long calculateDifference(Long todayValue, Long yesterdayValue) {
        if (todayValue == null || yesterdayValue == null) {
            return null;
        }
        return todayValue - yesterdayValue;
    }
}
